package core;

import io.XMLReader;

import java.io.File;
import java.util.*;

import org.jdom.*;

public class PluginManager {
	
	
	public PluginManager() {
		Timer timer = new Timer();
		timer.schedule(new Refresher(), 0, 5 * 1000);		
	}
	
	
	public synchronized Collection<Plugin> list() {
		return plugins.values();
	}


	public synchronized boolean containsPlugin(String name) {
		return plugins.containsKey(name);
	}
	
	
	public synchronized Plugin getPlugin(String name) {
		return plugins.get(name);
	}
	
	
	private synchronized void addPlugin(String pluginName, String pluginClass, long version, boolean autoRun) {
		Plugin plugin = null;
		try {
			plugin = (Plugin) Class.forName(pluginClass).newInstance();
			plugin.setVersion(version);
			plugin.load(Controller.getInstance());
			plugins.put(pluginName, plugin);
			
			System.err.println("[INFO] Deployed plugin " + pluginName);
			
			if (autoRun) {
				plugin.start();
				System.err.println("[INFO] Started plugin " + pluginName);
			}
		} catch (Exception e) {
			System.err.println("[ERROR] Failed to deploy plugin " + pluginName);
			e.printStackTrace();
		}
	}
	
	
	private synchronized void removePlugin(String pluginName) {
		plugins.remove(pluginName);
	}
	

	public boolean startPlugin(String pluginName) {
		if (!containsPlugin(pluginName)) 
			return false;
		
		Plugin plugin = getPlugin(pluginName);
		if (plugin.isRunning())
			return false;
		
		plugin.start();
		
		return plugin.isRunning();
	}
	
	
	public boolean stopPlugin(String pluginName) {
		if (!containsPlugin(pluginName)) 
			return false;
		
		Plugin plugin = getPlugin(pluginName);
		if (!plugin.isRunning())
			return false;
		
		plugin.stop();
		
		return true;
	}
			

	private Map<String, Plugin> plugins = new HashMap<String, Plugin>();
	
	
	private class Refresher extends TimerTask {

		@Override
		public void run() {
			List<File> plgFiles = findPlgFiles();
			for (File file : plgFiles) {
				try {
					Object[] pluginInfo = readPluginInfo(file);
					String pluginName = (String) pluginInfo[0];
					String pluginClass = (String) pluginInfo[1];
					boolean autoRun = (Boolean) pluginInfo[2];
					
					if (!containsPlugin(pluginName)) {
						addPlugin(pluginName, pluginClass, System.currentTimeMillis(), autoRun);
					} else if (file.lastModified() > getPlugin(pluginName).getVersion() && !getPlugin(pluginName).isRunning()) {
						removePlugin(pluginName);
						addPlugin(pluginName, pluginClass, System.currentTimeMillis(), autoRun);
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		
		
		private Object[] readPluginInfo(File file) {
			Document document = new XMLReader().readXML(file);
			Element root = document.getRootElement();
			
			String pluginName = root.getAttributeValue("name");
			String pluginClass = root.getAttributeValue("class");
			boolean autoRun = false;
			
			Attribute autoRunAttr = root.getAttribute("autorun");
			if (autoRunAttr != null) {
				try {
					autoRun = autoRunAttr.getBooleanValue();
				} catch (DataConversionException e) {
				}
			}
			
			return new Object[] { pluginName, pluginClass, autoRun };
		}
		
		
		private List<File> findPlgFiles() {
			File file = new File(System.getProperty("user.dir") + "/plugins/");
			if (file.exists())
				return findPlgFiles(file);
			
			return new ArrayList<File>();
		}


		private List<File> findPlgFiles(File dir) {
			List<File> plgFiles = new ArrayList<File>();
			
			File[] files = dir.listFiles();
			for (File file : files) {
				if (file.isDirectory()) {
					plgFiles.addAll(findPlgFiles(file));
				} else	if (file.getName().equals("plugin.xml")) {
					plgFiles.add(file);
				} 
			}
			
			return plgFiles;
		}
	}
}
